#include "temp_logger.h"








//FUNCTIONS


/****Initialize "A one second" interrupt Timer/counter2****/
void init_interrupt(void)		
{	
	WAIT_SEC(1)								// Wait for external crystal to stabilize
			
    cli();									// Disbale global interrupt

    
	CLEAR_BIT(TIMSK2, TOIE2)				// Disbale the timer output interrupt enable
	
	ASSR = (1<<AS2);						// Select Timer2 asynchronous operation

    TCNT2 = 0;								// Clear the Timer/Counter2 count register
	
	
    TCCR2A |= (1<<CS22) | (1<<CS20);		// Select precaler: 32.768 kHz / 128 = 1 sec between each overflow
	
	
    while((ASSR & 0x01) | (ASSR & 0x04));	// Wait for TCN2UB and TCR2UB to be cleared	

    TIFR2 = 0xFF;							// Clear Interrupt Flags Regeister
    SET_BIT(TIMSK2, TOIE2)					// Enable the timer output interrupt enable

    sei();									// Enable global interrupts
}

/****** Disable "The one second interrupt" ******/
void disable_interrupt(void)
{
	cli();									// Disbale global interrupt
	CLEAR_BIT(TIMSK2, TOIE2)				// Disbale the timer output interrupt enable

    sei();									// Enable global interrupts
}

/****** Store the value to Dataflash ******/
void store_data(void)
{
	INIT_DF
	
	int temp;
	char tempc[2],counter_day_c[3],counter_hour_c[2],counter_min_c[2];

	TEMPERATURE(temp)

	itoa(temp, tempc, 10);
	
	strcat(data,tempc);
	strcat(data,"C ");
	strcat(data,counter_day_c);
	strcat(data," : ");
	strcat(data,counter_hour_c);
	strcat(data,":");
	strcat(data,counter_min_c);


	WRITE_STR_BUFFER(page,20,data);

	page++;

	if(page==2048)		//reset page number if memory is full
	{
		page=0;
		overwrite_flag = 1;
	}
	

	END_DF
}

/****Compare if it's the time to store a value *****/
void compare_time(void)
{
	uint16_t minutes = counter_min+counter_hour*60+counter_day*24*26; // calculate actual time in minutes

	
	if(compare_timer == minutes)							// compare actual time with the next storage time
	{
		store_data();
		compare_timer = compare_timer + interval_min;
	}
}

/****Function triggered by the Timer/counter2 interrupt****/
SIGNAL(SIG_OVERFLOW2)
{
	counter_sec++;

	if(counter_sec > 59)
	{
		counter_min++;
		counter_sec = 0;
	}
	if(counter_min > 59)
	{
		counter_hour++;
		counter_min = 0;
	}
	if(counter_hour > 23)
	{
		counter_day++;
		counter_hour = 0;
	}

	compare_time();
	
}

	

/****Setting the measurement intervall *****/
void set_interval(void)
{	
	while(1)		// confirmation for transfer data
	{	
		LCD_TEXT("SET TIME?")

		ON_JOYSTICK_CENTER
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING	
				leave_flag = 0;
				break;
			}
		ON_JOYSTICK_LEFT
			{
				WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING	
				leave_flag = 1;
				break;
			}
	}

	if(!leave_flag)
	{

		int intervall_change_new = 0, intervall_change_old = 0, start_flag=0;
		uint8_t change_flag = 2, new_interval_flag = 0, compare_flag = 0;	// Flags used in this function
		uint8_t compare_time = 0;		// Time Variables used in this function
	
	
		char hrs_dis[7] = {0,0,0,0,0,0,0}; //display current measuremt interval
		char min_dis[3] = {0,0,0};

		itoa(hrs,hrs_dis,10);
		itoa(min,min_dis,10);

		strcat(hrs_dis, ":");
		strcat(hrs_dis, min_dis);

		LCD_TEXT(hrs_dis);

	
		while(1)
		{
			ON_JOYSTICK_CENTER
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING	
				CLEAR_LCD
				LCD_TEXT("00:00")
				start_flag = 1;
			}
		
	
	
			while(start_flag)								// Infinite while loop till break
			{	
				ON_JOYSTICK_LEFT					// Shifting to hrs variable
				{
					WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING
					change_flag = 1;
				}
				ON_JOYSTICK_RIGHT					// Shifting to min variable
				{
					WAIT_FOR_RELEASE_JOYSTICK_RIGHT DO_NOTHING
					change_flag = 2;
				}
		
				if(change_flag==1)
				{
					ON_JOYSTICK_UP					// increasing hrs variable till max 24
					{
						WAIT_FOR_RELEASE_JOYSTICK_UP DO_NOTHING
						hrs++;
	
						if(hrs==25)
						{
							hrs=0;
						}
					}
					ON_JOYSTICK_DOWN		// decreasing hrs variable till minimum 0
					{
						WAIT_FOR_RELEASE_JOYSTICK_DOWN DO_NOTHING
						hrs--;

						if(hrs==-1)
						{
							hrs=24;
						}
					}
				}

				if(change_flag==2)
				{
					ON_JOYSTICK_UP			// increasing min variable till max 55
					{
						WAIT_FOR_RELEASE_JOYSTICK_UP DO_NOTHING
						min = min + 5;

						if(min==60)
						{
							min = 0;
						}
					}

					ON_JOYSTICK_DOWN		// decreasing min variable till minimum 0
					{
						WAIT_FOR_RELEASE_JOYSTICK_DOWN DO_NOTHING
						min = min - 5;

						if(min==-5)
						{
							min=55;
						}
					}
				}

				intervall_change_new = min + (hrs * 60);	// measurement intervall in min
		
				if(intervall_change_new != intervall_change_old) // display changed intervall value
				{
					itoa(hrs,hrs_dis,10);
					itoa(min,min_dis,10);

					strcat(hrs_dis, ":");
					strcat(hrs_dis, min_dis);

					LCD_TEXT(hrs_dis);
				} 

				intervall_change_old = intervall_change_new; 		//store current intervall value

				ON_JOYSTICK_CENTER						// break while loop when joystick center is pressed
				{
					LCD_TEXT("SET!")
					compare_time = counter_sec+3;
					if(compare_time<counter_sec)
					{
						compare_time = counter_sec-7;
						compare_flag = 1;
					}
					else
						compare_flag = 0;
				
			
					WAIT_FOR_RELEASE_JOYSTICK_CENTER 	//if center button is pressed for more then 3 sec new intervall value is set
					{
						if(compare_flag == 0)
						{
							if(compare_time == counter_sec)
							{
								new_interval_flag = 1;
								break;
							}
						}
						else if(compare_flag == 1)
						{
							if(compare_time == counter_sec-10)
							{
								new_interval_flag = 1;
								break;
							}
						}
						CLEAR_LCD
					}
				}

			

				if(new_interval_flag == 1)
				{
					LCD_TEXT("STARTED");
				
					interval_min = intervall_change_new; //set new intervall
				
					counter_sec = 0; // reset all variables for measurement
					counter_min = 0;
					counter_hour = 0;
					counter_day = 0;
					compare_timer = 0;

					page = 0;
					overwrite_flag = 0;
					
					break;
				}
			}
		if(new_interval_flag == 1)
			break;
		}
	}
}

/****Transfer Data to PC*****/
void transfer_data(void)
{
	
	while(1)		// confirmation for transfer data
	{	
		LCD_TEXT("TRANSFER?")

		ON_JOYSTICK_CENTER
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING	
				leave_flag = 0;
				break;
			}
		ON_JOYSTICK_DOWN
			{
				WAIT_FOR_RELEASE_JOYSTICK_DOWN DO_NOTHING	
				leave_flag = 1;
				break;
			}
	}

	if(!leave_flag)
	{
		int i;

		INIT_DF
		USARTinit();	

		if(overwrite_flag==1)
		{
			for (i=0;i<2048;i++)
			{
				READ_STR_BUFFER(i,20,a)
				strcat(a,"     ");

				sendString(a);
			}
		}
		if(overwrite_flag==0)
		{
			for (i=0;i<=page;i++)
			{
				READ_STR_BUFFER(i,20,a)
				strcat(a,"     ");

				sendString(a);
			}
		}

		USARTdisable();
		END_DF
	}
}

/****Display Temperature*****/
void display_temp(void)
{
	INIT_DF
	
	uint16_t actual_page = 0, actual_page_old = 0;		// page number which is being displayed (old for while loop comparsion)
	//	uint8_t leave_flag = 0;		// variable declared in header file
	
	actual_page = page;				// set displayed page to last written page

	while(1)
	{
		LCD_TEXT("SHOW?")

		ON_JOYSTICK_CENTER
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING	
				leave_flag = 0;
				break;
			}
		ON_JOYSTICK_UP
			{
				WAIT_FOR_RELEASE_JOYSTICK_UP DO_NOTHING	
				leave_flag = 1;
				break;
			}
	}

	if(!leave_flag)
	{
		LCD_TEXT("UP/DOWN")
		WAIT_SEC(3)
	
		READ_STR_BUFFER(actual_page,255,data)			//display the current temp value
		LCD_TEXT(data)

		while(1)
		{
			if(actual_page != actual_page_old)
			{
				READ_STR_BUFFER(actual_page,20,data)	
				LCD_TEXT(data)
			}	

			ON_JOYSTICK_UP								// increasing displayed temp
			{
				WAIT_FOR_RELEASE_JOYSTICK_UP DO_NOTHING
				if(actual_page == 2047 || actual_page == page)
					DO_NOTHING
				else
					actual_page++;
			}
				
				
				
			ON_JOYSTICK_DOWN							// decreasing displayed temp
			{
				WAIT_FOR_RELEASE_JOYSTICK_DOWN DO_NOTHING
				if(actual_page == 0)
					DO_NOTHING
				else
					actual_page--;
			}
		
			actual_page_old = actual_page;

			ON_JOYSTICK_CENTER						// break while loop when joystick center is pressed
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING 	//if center button is pressed for more then 3 sec new intervall value is set
				break;
			}
		}
	}

	END_DF		
}

/****Pause/Continue Measurement*****/
void pause_continue(void)
{
	if(pause_flag)												//measurement paused or running? pause_flag == 1  => Paused
	{
		LCD_TEXT("RESUME?")
		while(1)
		{
			ON_JOYSTICK_CENTER									
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING 	//if center button is pressed continue the measurement
				init_interrupt;
				pause_flag=0;
				break;											//break while loop if joystick center is pressed
			}				
			ON_JOYSTICK_LEFT									
			{
				WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING 		//if left button is pressed do nothing and leave the function
				break;											//break while loop if joystick left is pressed
			}				
		}
	}
	else
	{
		LCD_TEXT("PAUSE?")
		while(1)
		{
			ON_JOYSTICK_CENTER									
			{
				WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING 	//if center button is pressed pause the measurement
				disable_interrupt;
				pause_flag=1;
				LCD_TEXT("PAUSED!")
				WAIT_SEC(3)
				break;											//break while loop if joystick center is pressed
			}				
			ON_JOYSTICK_LEFT					
			{
				WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING 		//if left button is pressed do nothing and leave the function
				break;											//break while loop if joystick left is pressed
			}						
		}		
	}		
}	

/****Sleep Mode (Power Safe Mode)*****/
void sleepmode(void)
{
	uint8_t restart_counter = 0;		//counter variable to check if the user wants to leave sleep mode
	uint8_t compare_time_flag = 0;		//compare flag (counter_sec>50)
	
	LCD_disable();						//disable LCD
	
	while(1)
	{
		ON_JOYSTICK_CENTER 					//if the user presses the center button >5sec leave sleep mode
		{
			restart_counter = counter_sec;
			if(counter_sec < 50)
				compare_time_flag = 0;
			else
				compare_time_flag = 1;
			
			WAIT_FOR_RELEASE_JOYSTICK_LEFT
			{
				if(!compare_time_flag)
				{
					if((counter_sec-5)>restart_counter)
					{
						restart_counter = 100;
						break;
					}
				}
				else
				{
					if(counter_sec+60>100)
					{
						if((counter_sec-5)>restart_counter)
						{
							restart_counter = 100;
							break;
						}
					}
					else
					{
						if((counter_sec+60-5)>restart_counter)
						{
							restart_counter = 100;
							break;
						}
					}
				}
			}
		}
		if(restart_counter==100)
		{
				ACTIVATE_LCD 		// initialize the LCD. The output begins at the first position of the display.
				CLEAR_LCD 			// Clears the LCD screen.
				break;				//break while loop -> leave sleep mode
		}
	}
}


/****Disbale LCD****/
void LCD_disable(void)
{
	/* Wait until a new frame is started. */
	while ( !(LCDCRA & (1<<LCDIF)) )
	;
	/* Set LCD Blanking and clear interrupt flag */
	/* by writing a logical one to the flag. */
	LCDCRA = (1<<LCDEN)|(1<<LCDIF)|(1<<LCDBL);
	/* Wait until LCD Blanking is effective. */
	while ( !(LCDCRA & (1<<LCDIF)) )
	;
	/* Disable LCD */
	LCDCRA = (0<<LCDEN);
}

/*******Reset the programm******/
int reset(void)
{
	LCD_TEXT("RESET?")
	while(1)
	{	
		ON_JOYSTICK_CENTER						// return 1 if joystick center is pressed
		{
			WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING 	//if center button is pressed reset device
			return(1);
		}				
		ON_JOYSTICK_LEFT					// return 0 if joystick left is pressed
		{
			WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING 	//if left button is pressed go back to menu state
			LCD_TEXT("DONE!")
			WAIT_SEC(3)
			return(0);
		}						
	}
}



PROGRAM_INIT

state = 0;  //init state

PROGRAM_START
	
	
	
	if(state==0) //Init
	{
		//***init variables***//

		interval_min = min = 5; 	// Measurement intervall (default is 5 min)
		hrs = 0;

		counter_sec = 0; 	//counters for time measurement
		counter_min = 0;
		counter_hour = 0;
		counter_day = 0;
		compare_timer = 0;

		sleep_counter = 0; 	// variable to go into sleep_mode

		page = 0;			//storage page in flash memory



		menu_choose = 0; 		//menu variable (run once)
		sleep_mode_counter = 0; //variable for sleep_mode activation

		overwrite_flag = 0;		//flag   1:memory full start overwriting values    0: memory not yet full
		pause_flag = 0;			//is the temp storage paused? 0=NO  1=YES

		//***init functions and go on in state machine***//
		
		ACTIVATE_LCD 		// initialize the LCD. The output begins at the first position of the display.
		CLEAR_LCD 			// Clears the LCD screen.	

		//INIT_UART 			// uart initialisation done in the function

		init_interrupt(); 	//init timer/counter2 interrupt
		
		LCD_TEXT("WELCOME")
		WAIT_SEC(5)
		CLEAR_LCD

		sleep_counter = counter_sec; 	//reset sleep_mode counter
		state=7;						//Go to menu state
	}
	
	
	else if(state==7) //menu_state
	{
		if(menu_choose==0) //Only do this once
		{
			LCD_TEXT("MENU ON")
			WAIT_SEC(2)
			menu_choose++;
		}
		

		ON_JOYSTICK_UP //Go to transfer_data
		{
			WAIT_FOR_RELEASE_JOYSTICK_UP DO_NOTHING
			CLEAR_LCD
			LCD_TEXT("Transfer Data")
			WAIT_SEC(2)
			state = 1;
			menu_choose=0;
		}
		ON_JOYSTICK_LEFT //Go to reset_device
		{
			WAIT_FOR_RELEASE_JOYSTICK_LEFT DO_NOTHING
			CLEAR_LCD
			LCD_TEXT("Reset Device")
			WAIT_SEC(2)
			state = 2;
			menu_choose=0;
			
		}
		ON_JOYSTICK_DOWN //Go to display temp
		{
			WAIT_FOR_RELEASE_JOYSTICK_DOWN DO_NOTHING
			CLEAR_LCD
			LCD_TEXT("Display Temp")
			WAIT_SEC(2)
			state = 3;
			menu_choose=0;
		}
		ON_JOYSTICK_RIGHT //Go to set interval
		{
			WAIT_FOR_RELEASE_JOYSTICK_RIGHT DO_NOTHING
			CLEAR_LCD
			LCD_TEXT("Set Intervall")
			WAIT_SEC(2)
			state = 4;
			menu_choose=0;
		}
		ON_JOYSTICK_CENTER //Go to Pause/Continue
		{
			WAIT_FOR_RELEASE_JOYSTICK_CENTER DO_NOTHING
			CLEAR_LCD
			LCD_TEXT("Pause/Continue")
			WAIT_SEC(2)
			state = 5;
			menu_choose=0;
		}



		sleep_counter++;
		if(sleep_counter == counter_sec)	//go in sleep_mode after 1 min no activity
		{	
			state = 6;
			menu_choose = 0;
		}
			
	}		


	else if(state == 1) //transfer_data	
	{
		transfer_data();
		sleep_counter = counter_sec; //reset sleep_mode counter
		state = 7;			//go back to menu state
	}
	
	else if(state == 2) //reset
	{
		if(reset())
			state = 0; // go back to init state
		else
		{	
			sleep_counter = counter_sec; //reset sleep_mode counter
			state = 7; //go back to menu_state
		}
	}	
	
	else if(state == 3) //display_temp
	{
		display_temp();
		sleep_counter = counter_sec; //reset sleep_mode counter
		state = 7;			//go back to menu state
	}

	else if(state == 4)	//set_interval
	{
		set_interval();
		sleep_counter = counter_sec; //reset sleep_mode counter
		state = 7;			//go back to menu state
	}

	else if(state == 5)	//pause_measurement
	{
		pause_continue();	
		sleep_counter = counter_sec; //reset sleep_mode counter
		state = 7;		//go back to menu state
	}

	else if(state == 6)	//sleep_mode
	{
		sleepmode();
		sleep_counter = counter_sec; //reset sleep_mode counter
		state = 7;			//go back to menu state
	}





PROGRAM_END
